home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 19 / Mac Magazin and MacEasy Magazine CD - Issue 19.iso / Musik & Kunst / Ear Workout 2.1 / source code / ear_sound.cp < prev    next >
Text File  |  1996-01-08  |  6KB  |  202 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <OSUtils.h>
  4. #include <QuickDraw.h>
  5. #include <Sound.h>
  6.  
  7. #define NEED_MAC_STUFF 1
  8.  
  9. #include "Ninkasi:C++ util:generic.h"
  10. #include "Ninkasi:C++ util:complete_window.h"
  11. #include "ear_defines.h"
  12. #include "ear_decl.h"
  13. #include "ear_prototypes.h"
  14.  
  15.     // returns avg of left and right volumes; 
  16.     // 256 = max normal vol
  17.     int
  18. get_current_volume(SndChannelPtr snd_chan)
  19.     {
  20.       SndCommand my_snd_command;
  21.       union {
  22.         long the_volumes;
  23.         short vol[2];
  24.       } vol_data;
  25.       my_snd_command.cmd = getVolumeCmd;
  26.       my_snd_command.param2 = (long) &(vol_data.the_volumes);
  27.       SndDoImmediate(snd_chan,&my_snd_command);
  28.       return (int) (.5*(vol_data.vol[0]+vol_data.vol[1]));
  29.     }
  30.     
  31.     void
  32. set_volume(int new_volume,SndChannelPtr snd_chan)
  33.     {
  34.       SndCommand my_snd_command;
  35.       union {
  36.         long the_volumes;
  37.         short vol[2];
  38.       } vol_data;
  39.       my_snd_command.cmd = volumeCmd;
  40.       vol_data.vol[0] = new_volume;
  41.       vol_data.vol[1] = new_volume;
  42.       my_snd_command.param2 = vol_data.the_volumes;
  43.       SndDoImmediate(snd_chan,&my_snd_command);
  44.     }
  45.  
  46.     // The first time this routine is called, everything is computed from
  47.     // scratch.
  48.     // On subsequent calls, the default behavior is to simply rescale the
  49.     // floating-point version of the waveform, and the "kind" parameter
  50.     // is ignored.
  51.     // To force a recalculation from scratch, set both have_wave_table
  52.     // and have_temp_wave_table to zero.
  53.     void
  54. do_waveforms(
  55.     SndChannelPtr *my_snd_chan,
  56.     int kind,
  57.     double amplitude,
  58.     int chans_used,
  59.     unsigned char *wave_table,
  60.     double *temp_storage,
  61.     int wave_table_size)
  62.         {
  63.           dispose_of_chans(chans_used,my_snd_chan); 
  64.               //..in case they were already installed
  65.       make_sound_channels(chans_used,init_chan_list,kind_of_chan_list,my_snd_chan);
  66.       if (!have_wave_table) {
  67.         make_wave_table(wave_table,temp_storage,kind,amplitude,wave_table_size,
  68.                     !have_temp_wave_table);
  69.         have_wave_table = 1;
  70.         have_temp_wave_table = 1;
  71.       }
  72.           install_waveforms(chans_used,my_snd_chan,wave_table,wave_table_size,kind_of_chan_list);          
  73.         }
  74.  
  75.     void
  76. play_chord(int notes_in_chord,
  77.     SndChannelPtr *my_snd_chan,
  78.     int *note,
  79.     int duration, //-- in half-milliseconds
  80.     int if_wait)
  81.         {
  82.           int delay_ticks,i;
  83.           SndCommand my_snd_cmd;
  84.           OSErr my_err;
  85.  
  86.       set_up_sound();
  87.           
  88.           for (i=0; i<=notes_in_chord-1; i++) {
  89.             my_snd_cmd.cmd = freqDurationCmd;
  90.             my_snd_cmd.param1 = duration;
  91.             my_snd_cmd.param2 = note[i]+pitch_offset;
  92.             my_err = SndDoCommand(my_snd_chan[i],&my_snd_cmd,FALSE);
  93.             if (my_err!=0) {
  94.               bail_out("error playing sound");
  95.             }
  96.           }
  97.           if (if_wait) {
  98.             delay_ticks = duration/33.33333;
  99.             delay_some(delay_ticks);
  100.             wait_until_chan_not_busy(my_snd_chan[notes_in_chord-1],1);
  101.           }
  102.           
  103.           dispose_of_chans(chans_used,my_snd_chan);
  104.               // Let other programs have sound channels.  Also, make sure
  105.               // sound channels are available for parts of this program
  106.               // that use other synthesizers other than the wavetable one.
  107.           
  108.         }
  109.         
  110.     void
  111. wait_until_chan_not_busy(SndChannelPtr my_snd_chan,int max_secs)
  112.         {
  113.           unsigned long count;
  114.           int max_ticks;
  115.           OSErr my_err;
  116.           SCStatus my_sc_status;
  117.           max_ticks = max_secs*60;
  118.           count = 0;
  119.           do {
  120.             my_err = SndChannelStatus(my_snd_chan,sizeof(SCStatus),&my_sc_status);
  121.             delay_some(1); /* 1 tick = 1/60 sec */
  122.             ++count;
  123.           } while(my_sc_status.scChannelBusy && count<max_ticks);
  124.         }
  125.  
  126.     void
  127. rest(int nhalf_ms)
  128.         {
  129.           delay_some((int) (nhalf_ms/33.33333));
  130.         }
  131.  
  132.     void
  133. delay_some(int nticks)
  134.         {
  135.           unsigned long delay_ticks,sys_time;
  136.           delay_ticks = nticks;
  137.           Delay(delay_ticks,(long *) &sys_time);
  138.         }
  139.         
  140.         void
  141. install_waveforms(int nchan,SndChannelPtr *my_snd_chan,
  142.     unsigned char *my_wave_table,int wave_table_size,short *kind_of_chan_list)
  143.         {
  144.           int i;
  145.           SndCommand my_snd_cmd;
  146.           OSErr my_err;
  147.           my_snd_cmd.cmd = waveTableCmd;
  148.           my_snd_cmd.param1 = wave_table_size;
  149.           my_snd_cmd.param2 = (long) my_wave_table;
  150.           for (i=0; i<nchan; i++) {
  151.             if (kind_of_chan_list[i]==waveTableSynth) {
  152.               if (!made_snd_chan[i]) bail_out("channel not made yet in install_waveforms");
  153.               my_err = SndDoCommand(my_snd_chan[i],&my_snd_cmd,FALSE);
  154.               if (my_err!=0) {
  155.                 char s[200];
  156.                 sprintf(s,"error in install_waveforms, i=%d, my_err=%d, my_snd_chan[i]=%08lx\n",
  157.                       (int) i,(int) my_err,(long) my_snd_chan[i]);
  158.                 bail_out(s);
  159.               }
  160.             }
  161.           }
  162.         }
  163.  
  164.     void
  165. make_sound_channels(
  166.     int chans_used,
  167.     long *init_chan_list,
  168.     short *kind_of_chan_list,
  169.     SndChannelPtr *my_snd_chan) /* array of pointers to sound channels */
  170.         {
  171.           int i;
  172.           OSErr my_err;
  173.           dispose_of_chans(chans_used,my_snd_chan);
  174.           for (i=0; i<chans_used; i++) {
  175.             my_snd_chan[i] = NULL; /* tells it I need a new channel allocated on heap */
  176.             my_err = SndNewChannel(&my_snd_chan[i],
  177.                                       kind_of_chan_list[i],init_chan_list[i],NULL);
  178.             if (my_err!=0) {
  179.               bail_out("error in SndNewChannel\n");
  180.             }
  181.             made_snd_chan[i] = 1;
  182.           }
  183.         }
  184.  
  185.     void
  186. dispose_of_chans(
  187.     int chans_used,
  188.     SndChannelPtr *my_snd_chan)  /* array of pointers to sound channels */
  189.         {
  190.           int i;
  191.           OSErr my_err;
  192.           for (i=0; i<=chans_used-1; i++) {
  193.             if (made_snd_chan[i] && VALID_POINTER(my_snd_chan[i])) {
  194.               my_err = SndDisposeChannel(my_snd_chan[i],(Boolean) 1);
  195.                         /* 0=await completion, 1=immediate return */
  196.               made_snd_chan[i] = 0;
  197.               my_snd_chan[i] = (SndChannelPtr) 0;
  198.             }
  199.           }
  200.         }
  201.  
  202.